package service

import (
	"errors" // 错误处理包
	"gin_gorm_oj/core"
	"gin_gorm_oj/define"
	"gin_gorm_oj/helper"
	"gin_gorm_oj/models"       // 数据模型包
	"github.com/gin-gonic/gin" // Gin Web框架
	"gorm.io/gorm"             // GORM数据库ORM框架
	"log"
	"net/http" // HTTP状态码和请求处理
	"strconv"
	"time"
)

// GetUserDetail
// @Tags 公共方法
// @Summary 用户详情
// @Param identity query string false "用户唯一标识"
// @Success 200 {string} JSON "{"code":"200","data":"{}"}"
// @Router /user-detail [get]
func GetUserDetail(c *gin.Context) { // 获取用户详情处理函数
	identity := c.Query("identity") // 获取用户唯一标识参数
	if identity == "" {             // 检查标识是否为空
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "用户标识不能为空"}) // 返回参数错误响应
		return                                                      // 终止处理
	}
	var data models.User // 声明用户数据模型变量
	// 根据标识查询用户数据 忽略密码
	err := models.DB.Omit("password").Where("identity = ?", identity).First(&data).Error

	if err != nil { // 检查查询错误
		if errors.Is(err, gorm.ErrRecordNotFound) { // 判断是否为记录未找到错误
			c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "用户不存在"}) // 返回用户不存在响应
			return                                                   // 终止处理
		}
		c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "Get UserDetail Error:" + err.Error()}) // 返回查询错误响应
		return                                                                                 // 终止处理
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "data": data}) // 返回成功响应，包含用户数据
}

// Login 用户登录
// @Tags 公共方法
// @Summary 用户登录
// @Param username formData string false "username"
// @Param password formData string false "password"
// @Success 200 {string} json {"code":"200","data":""}
// @Router /login [post]
func Login(c *gin.Context) {
	username := c.PostForm("username") // 获取表单中的用户名（key为"username"）
	password := c.PostForm("password") // 获取表单中的密码（key为"password")

	// 检查用户名或密码是否为空
	if username == "" || password == "" {
		// 返回错误响应：必填信息不能为空
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "必填信息为空",
		})
		return // 终止函数执行
	}

	// 对密码进行MD5加密处理
	password = helper.GetMd5(password)
	var data models.User // 声明用户数据模型变量
	//println(username, password)

	// 查询数据库：根据用户名和密码查找用户
	err := models.DB.Where("name = ? AND password = ?", username, password).First(&data).Error

	// 错误处理
	if err != nil {
		// 用户不存在的情况
		if errors.Is(err, gorm.ErrRecordNotFound) {
			c.JSON(http.StatusOK, gin.H{
				"code": -1,
				"msg":  "用户名或密码错误",
			})
			return
		}

		// 其他数据库错误
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Get User Error:" + err.Error(),
		})
		return
	}

	// 生成JWT token
	token, err := helper.GenerateToken(data.Identity, data.Name, data.IsAdmin)
	// 错误处理：token生成失败
	if err != nil {
		// 返回错误响应：token生成错误
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "GenerateToken Error:" + err.Error(),
		})
		return // 终止后续执行
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"data": map[string]interface{}{
			"token": token,
		},
	})

}

// SendCode 发送验证码接口
// @Tags 公共方法
// @Summary 发送验证码
// @Param email formData string true "邮箱地址"
// @Success 200 {string} json {"code":"200","data":""}
// @Router /send-code [post]
func SendCode(c *gin.Context) {
	// 从表单获取邮箱参数
	email := c.PostForm("email")
	// 检查邮箱是否为空
	if email == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不正确",
		})
		return
	}

	//code := "123456"
	code := helper.GetRand()

	// 将验证码存入Redis，设置5分钟过期时间
	core.RDB.Set(c, email, code, time.Second*300)

	// 调用helper发送验证码邮件
	err := helper.SendCode(email, code)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Send Code Error:" + err.Error(),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "验证码发送成功",
	})
}

// Register 用户注册
// @Tags 公共方法
// @Summary 用户注册接口
// @Param mail formData string true "邮箱地址"
// @Param code formData string true "验证码"
// @Param name formData string true "用户名"
// @Param password formData string true "密码"
// @Param phone formData string false "手机号"
// @Success 200 {string} json "{"code":"200","data":""}"
// @Router /register [post]
func Register(c *gin.Context) {
	// 从POST表单中获取用户注册参数
	mail := c.PostForm("mail")         // 邮箱地址
	code := c.PostForm("code")         // 验证码
	name := c.PostForm("name")         // 用户名
	password := c.PostForm("password") // 密码
	phone := c.PostForm("phone")       // 手机号（可选）

	// 检查必填参数是否为空（手机号可选，不检查）
	if mail == "" || code == "" || name == "" || password == "" {
		// 返回参数错误响应
		c.JSON(http.StatusOK, gin.H{
			"code": -1,      // 错误状态码
			"msg":  "参数不正确", // 错误提示信息
		})
		return // 终止函数执行
	}

	// 验证验证码是否正确
	// 从Redis中获取指定邮箱对应的验证码
	sysCode, err := core.RDB.Get(c, mail).Result()
	if err != nil {
		// 返回JSON格式的错误响应
		c.JSON(http.StatusOK, gin.H{
			"code": -1,                              // 错误状态码
			"msg":  "Get Code Error:" + err.Error(), // 错误信息，包含具体错误详情
		})
		return // 终止函数执行，不再继续后续流程
	}

	if sysCode != code {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "验证码不正确",
		})
		return
	}

	// 判断邮箱是否已存在
	var cnt int64
	err = models.DB.Model(&models.User{}).Where("mail = ?", mail).Count(&cnt).Error
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "Get User Error:" + err.Error(),
		})
		return
	}
	if cnt > 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "该邮箱已被注册",
		})
		return
	}

	// 数据的插入
	// 创建用户基本信息结构体实例
	userIdentity := helper.GetUUID()
	data := &models.User{
		Identity: userIdentity,            // 生成唯一身份标识
		Name:     name,                    // 用户名
		Password: helper.GetMd5(password), // 密码MD5加密
		Phone:    phone,                   // 手机号
		Mail:     mail,                    // 邮箱
	}

	// 执行数据库插入操作
	err = models.DB.Create(data).Error

	// 错误处理：检查插入是否成功
	if err != nil {
		// 返回插入失败的JSON响应
		c.JSON(http.StatusOK, gin.H{
			"code": -1,                                 // 错误状态码
			"msg":  "Create User Error:" + err.Error(), // 错误信息
		})
		return // 终止函数执行
	}

	// 生成用户身份认证token
	token, err := helper.GenerateToken(userIdentity, name, data.IsAdmin)
	// 错误处理：token生成失败
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,                                    // 错误状态码
			"msg":  "Generate Token Error:" + err.Error(), // 错误详细信息
		})
		return // 终止执行
	}

	// token生成成功，返回给客户端
	c.JSON(http.StatusOK, gin.H{
		"code": 200, // 成功状态码
		"data": map[string]interface{}{
			"token": token, // 返回生成的token
		},
	})

}

// GetRankList
// @Tags 公共方法
// @Summary 用户排行榜
// @Param page query int false "page"
// @Param size query int false "size"
// @Success 200 {string } json {"code":"200","data": ""}
// @Router /rank-list [get]
func GetRankList(c *gin.Context) {
	// 获取每页显示数量，默认使用预定义值
	size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultSize))

	// 获取页码参数，默认使用预定义值
	page, err := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage))
	if err != nil {
		// 页码转换错误处理
		log.Println("GetProblemList Page strconv Error:", err)
		return
	}

	// 计算数据库查询的偏移量（跳过前面多少条记录）
	page = (page - 1) * size

	// 声明变量用于存储总记录数
	var count int64
	// 初始化空切片，用于存储查询结果
	var list []*models.User

	// 执行数据库查询：获取用户排行榜
	err = models.DB.Model(&models.User{}).
		Count(&count).                                    // 统计总记录数
		Order("finish_problem_num DESC, submit_num ASC"). // 按完成题目数降序，提交数升序排序
		Offset(page).                                     // 分页偏移量
		Limit(size).                                      // 每页数量限制
		Find(&list).                                      // 查询结果存入list
		Error                                             // 获取错误信息

	// 错误处理：查询失败时返回错误响应
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,                                   // 错误状态码
			"msg":  "Get Rank List Error:" + err.Error(), // 错误信息
		})
		return // 终止执行
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": map[string]interface{}{
			"list":  list,
			"count": count,
		},
	})
}
